/*
 * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package jdk.io;

import java.io.IOException;
import java.io.InputStream;

/**
 * <code>ByteArrayInputStream</code> 包含一个内部缓冲区，其中包含可从流中读取的字节。
 * 内部计数器跟踪 <code>read</code> 方法要提供的下一个字节。
 * <p>
 * 关闭 <tt>ByteArrayInputStream</tt> 没有效果。此类中的方法可以在流关闭后调用，
 * 而不会生成 <tt>IOException</tt>。
 *
 * @author  Arthur van Hoff
 * @since   JDK1.0
 */
public
class ByteArrayInputStream extends InputStream {

    /**
     * 由流的创建者提供的字节数组。元素 <code>buf[0]</code> 到 <code>buf[count-1]</code>
     * 是可从流中读取的唯一字节；元素 <code>buf[pos]</code> 是要读取的下一个字节。
     */
    protected byte buf[];

    /**
     * 要从输入流缓冲区读取的下一个字符的索引。此值应始终为非负且不大于 <code>count</code> 的值。
     * 要从输入流缓冲区读取的下一个字节将是 <code>buf[pos]</code>。
     */
    protected int pos;

    /**
     * 流中当前标记的位置。ByteArrayInputStream 对象在构造时默认在位置零处标记。
     * 它们可以通过 <code>mark()</code> 方法在缓冲区内的另一个位置标记。
     * 当前缓冲区位置通过 <code>reset()</code> 方法设置到此点。
     * <p>
     * 如果未设置标记，则标记的值是传递给构造函数的偏移量（如果未提供偏移量，则为 0）。
     */
    protected int mark = 0;

    /**
     * 输入流缓冲区中最后一个有效字符索引加一的值。
     * 此值应始终为非负数，且不大于 <code>buf</code> 的长度。
     * 它是可以从输入流缓冲区读取的 <code>buf</code> 中最后一个字节位置加一的值。
     */
    protected int count;

    /**
     * 创建 <code>ByteArrayInputStream</code>，使其使用 <code>buf</code> 作为其缓冲区数组。
     * 缓冲区数组不会被复制。
     * <code>pos</code> 的初始值为 <code>0</code>，<code>count</code> 的初始值为 <code>buf</code> 的长度。
     *
     * @param   buf   输入缓冲区。
     */
    public ByteArrayInputStream(byte buf[]) {
        this.buf = buf;
        this.pos = 0;
        this.count = buf.length;
    }

    /**
     * 创建使用 <code>buf</code> 作为其缓冲区数组的 <code>ByteArrayInputStream</code>。
     * <code>pos</code> 的初始值为 <code>offset</code>，
     * <code>count</code> 的初始值为 <code>offset+length</code> 和 <code>buf.length</code> 中的较小值。
     * 缓冲区数组不被复制。缓冲区的标记被设置为指定的偏移量。
     *
     * @param   buf      输入缓冲区。
     * @param   offset   缓冲区中第一个要读取的字节的偏移量。
     * @param   length   要从缓冲区读取的最大字节数。
     */
    public ByteArrayInputStream(byte buf[], int offset, int length) {
        this.buf = buf;
        this.pos = offset;
        this.count = Math.min(offset + length, buf.length);
        this.mark = offset;
    }

    /**
     * 从此输入流读取下一个数据字节。该字节值作为 <code>int</code> 返回，范围在 <code>0</code> 到 <code>255</code> 之间。
     * 如果由于到达流末尾而没有字节可用，则返回 <code>-1</code>。
     * <p>
     * 此 <code>read</code> 方法不会阻塞。
     *
     * @return  下一个数据字节，如果到达流末尾则为 <code>-1</code>。
     */
    public synchronized int read() {
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
    }

    /**
     * 从此输入流中将最多 <code>len</code> 字节的数据读入字节数组。
     * 如果 <code>pos</code> 等于 <code>count</code>，则返回 <code>-1</code> 以指示文件结束。
     * 否则，读取的字节数 <code>k</code> 等于 <code>len</code> 和 <code>count-pos</code> 中的较小值。
     * 如果 <code>k</code> 为正，则字节 <code>buf[pos]</code> 到 <code>buf[pos+k-1]</code>
     * 将通过 <code>System.arraycopy</code> 的方式复制到 <code>b[off]</code> 到 <code>b[off+k-1]</code>。
     * 值 <code>k</code> 将累加到 <code>pos</code> 并返回 <code>k</code>。
     * <p>
     * 此 <code>read</code> 方法不会阻塞。
     *
     * @param   b     读取数据的缓冲区。
     * @param   off   目标数组 <code>b</code> 中的起始偏移量
     * @param   len   读取的最大字节数。
     * @return  读入缓冲区的总字节数，如果由于到达流的末尾而没有更多数据，则返回 <code>-1</code>。
     * @exception  NullPointerException 如果 <code>b</code> 为 <code>null</code>。
     * @exception  IndexOutOfBoundsException 如果 <code>off</code> 为负，
     * <code>len</code> 为负，或 <code>len</code> 大于 <code>b.length - off</code>
     */
    public synchronized int read(byte b[], int off, int len) {
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        }

        if (pos >= count) {
            return -1;
        }

        int avail = count - pos;
        if (len > avail) {
            len = avail;
        }
        if (len <= 0) {
            return 0;
        }
        System.arraycopy(buf, pos, b, off, len);
        pos += len;
        return len;
    }

    /**
     * 从此输入流中跳过 <code>n</code> 字节的输入。如果到达流的末尾，跳过的字节可能较少。
     * 实际要跳过的字节数 <code>k</code> 等于 <code>n</code> 和 <code>count-pos</code> 中的较小值。
     * 值 <code>k</code> 将累加到 <code>pos</code> 并返回 <code>k</code>。
     *
     * @param   n   要跳过的字节数。
     * @return  实际跳过的字节数。
     */
    public synchronized long skip(long n) {
        long k = count - pos;
        if (n < k) {
            k = n < 0 ? 0 : n;
        }

        pos += k;
        return k;
    }

    /**
     * 返回可以从此输入流中读取（或跳过）的剩余字节数。
     * <p>
     * 返回的值为 <code>count&nbsp;- pos</code>，
     * 这是从输入缓冲区中读取的剩余字节数。
     *
     * @return  可以从此输入流中读取（或跳过）的剩余字节数，且不会阻塞。
     */
    public synchronized int available() {
        return count - pos;
    }

    /**
     * 测试此 <code>InputStream</code> 是否支持标记/重置。
     * <code>ByteArrayInputStream</code> 的 <code>markSupported</code> 方法始终返回 <code>true</code>。
     *
     * @since   JDK1.1
     */
    public boolean markSupported() {
        return true;
    }

    /**
     * 设置流中的当前标记位置。ByteArrayInputStream 对象在构造时默认在位置零处标记。
     * 它们可以通过此方法在缓冲区内的另一个位置标记。
     * <p>
     * 如果未设置标记，则标记的值是传递给构造函数的偏移量（如果未提供偏移量，则为 0）。
     *
     * <p> 注意：此类的 <code>readAheadLimit</code> 没有意义。
     *
     * @since   JDK1.1
     */
    public void mark(int readAheadLimit) {
        mark = pos;
    }

    /**
     * 将缓冲区重置到标记位置。标记位置为 0，除非标记了另一个位置或在构造函数中指定了偏移量。
     */
    public synchronized void reset() {
        pos = mark;
    }

    /**
     * 关闭 <tt>ByteArrayInputStream</tt> 没有效果。此类中的方法可以在流关闭后调用，
     * 而不会生成 <tt>IOException</tt>。
     */
    public void close() throws IOException {
    }

}
